/**
 * 
 */
package name.webdizz.gadget.four.envelope.client;

import name.webdizz.gadget.four.envelope.client.domain.Envelope;
import name.webdizz.gadget.four.envelope.client.domain.EnvelopeSize;
import name.webdizz.gadget.four.envelope.client.domain.Expense;
import name.webdizz.gadget.four.envelope.client.event.Events;
import name.webdizz.gadget.four.envelope.client.locale.Locale;
import name.webdizz.gadget.four.envelope.client.locale.LocaleFactory;
import name.webdizz.gadget.four.envelope.client.presenter.EnvelopePresenter;
import name.webdizz.gadget.four.envelope.client.presenter.HomeViewPresenter;
import name.webdizz.gadget.four.envelope.client.presenter.LoginViewPresenter;
import name.webdizz.gadget.four.envelope.client.view.EnvelopeView;
import name.webdizz.gadget.four.envelope.client.view.HomeView;
import name.webdizz.gadget.four.envelope.client.view.LoginView;

import com.google.gwt.gadgets.client.SetPrefsFeature;
import com.google.gwt.user.client.ui.RootPanel;
import com.mvp4g.client.event.Command;
import com.mvp4g.client.event.EventBus;

/**
 * MVP pattern configuration.
 * 
 * @author Izzet_Mustafayev
 * 
 */
public class Mvp {

	/**
	 * Reference to {@link SetPrefsFeature}.
	 */
	private SetPrefsFeature preferenceFeature;

	/**
	 * Reference to {@link EnvelopePreferences} instance.
	 */
	private EnvelopePreferences envelopePreferences;

	public Mvp(final EnvelopePreferences preferences,
			final SetPrefsFeature preferenceFeature) {
		this.preferenceFeature = preferenceFeature;
		this.envelopePreferences = preferences;
	}

	/**
	 * Starts Gadget.
	 */
	public void start() {
		final Locale locale = LocaleFactory.instance();
		EventBus eventBus = new EventBus();
		// configure home view module
		final HomeView homeView = new HomeView();
		final HomeViewPresenter homeViewPresenter = new HomeViewPresenter();
		homeViewPresenter.setEventBus(eventBus);
		homeViewPresenter.setView(homeView);
		homeViewPresenter.setEnvelopePreferences(envelopePreferences);
		homeViewPresenter.setPreferenceFeature(preferenceFeature);
		// application start command
		eventBus.addEvent(Events.START.name(), new Command<Object>() {
			public void execute(final Object form) {
				homeViewPresenter.onStart();
			}
		});

		// configure login view module
		final LoginView loginView = new LoginView();
		final LoginViewPresenter loginViewPresenter = new LoginViewPresenter();
		loginViewPresenter.setEventBus(eventBus);
		loginViewPresenter.setView(loginView);
		loginViewPresenter.setEnvelopePreferences(envelopePreferences);
		loginViewPresenter.setPreferenceFeature(preferenceFeature);
		// configure envelope view module
		final EnvelopeView envelopeView = new EnvelopeView();
		final EnvelopePresenter envelopePresenter = new EnvelopePresenter();
		envelopePresenter.setEventBus(eventBus);
		envelopePresenter.setView(envelopeView);
		envelopePresenter.setEnvelopePreferences(envelopePreferences);

		// register event for handle case when user hasn't entered credentials
		// yet
		eventBus.addEvent(Events.ENTER_CREDENTIALS.name(),
				new Command<Object>() {
					public void execute(final Object form) {
						homeViewPresenter.showContent(loginView);
					}
				});
		// register credentials saved event handler
		eventBus.addEvent(Events.CREDENTIALS_SAVED.name(),
				new Command<Object>() {
					public void execute(final Object form) {
						homeViewPresenter.showContent(envelopeView, locale
								.credentialsSaved());
						envelopePresenter.loadEnvelope();
					}
				});
		// register credentials reset event handler
		eventBus.addEvent(Events.CREDENTIALS_RESETED.name(),
				new Command<Object>() {
					public void execute(final Object form) {
						homeViewPresenter.showContent(loginView, locale
								.credentialsSaved());
						homeViewPresenter.setInfo("");
					}
				});
		// register show envelope event handler
		eventBus.addEvent(Events.LOAD_USER.name(), new Command<Object>() {
			public void execute(final Object form) {
				homeViewPresenter.showMessage(locale.userIsLoading());
				envelopePresenter.loadUser();
			}
		});
		// register show envelope event handler
		eventBus.addEvent(Events.SHOW_ENVELOPE.name(), new Command<Object>() {
			public void execute(final Object form) {
				homeViewPresenter.hideMessage();
				homeViewPresenter.showContent(envelopeView, locale
						.envelopeLoading());
				envelopePresenter.loadEnvelope();
			}
		});
		// register envelope not loaded event handler
		eventBus.addEvent(Events.ENVELOPE_WAS_NOT_LOADED.name(),
				new Command<String>() {
					public void execute(String message) {
						homeViewPresenter.showMessage(message);
					}
				});
		// register envelope was loaded event handler
		eventBus.addEvent(Events.ENVELOPE_WAS_LOADED.name(),
				new Command<Envelope>() {
					public void execute(Envelope envelope) {
						envelopePresenter.showEnvelope(envelope);
						homeViewPresenter.hideMessage();
					}
				});
		// register expense is going to be saved event handler
		eventBus.addEvent(Events.SAVE_EXPENSE.name(), new Command<Object>() {
			public void execute(final Object form) {
				homeViewPresenter.showMessage(locale.expenseSaving());
			}
		});
		// register expense was saved event handler
		eventBus.addEvent(Events.EXPENSE_SAVED.name(), new Command<Expense>() {
			public void execute(Expense expense) {
				envelopePresenter.onExpenseSaved(expense);
				homeViewPresenter.hideMessage();
			}
		});
		// register envelope size update event handler
		eventBus.addEvent(Events.UPDATE_ENVELOPE_SIZE.name(),
				new Command<EnvelopeSize>() {
					public void execute(EnvelopeSize envelopeSize) {
						homeViewPresenter.updateEnvelopeSize(envelopeSize);
					}
				});
		// register goal is going to be credited event handler
		eventBus.addEvent(Events.CREDIT_GOAL.name(), new Command<Object>() {
			public void execute(final Object form) {
				homeViewPresenter.showMessage(locale.creditGoal());
			}
		});
		// register goal was credited event handler
		eventBus.addEvent(Events.GOAL_CREDITED.name(), new Command<Object>() {
			public void execute(final Object form) {
				homeViewPresenter.hideMessage();
			}
		});
		// register expense is going to be credited event handler
		eventBus.addEvent(Events.CREDIT_EXPENSE.name(), new Command<Object>() {
			public void execute(final Object form) {
				homeViewPresenter.showMessage(locale.creditExpense());
			}
		});
		// register expense was credited event handler
		eventBus.addEvent(Events.EXPENSE_CREDITED.name(),
				new Command<Object>() {
					public void execute(final Object form) {
						homeViewPresenter.hideMessage();
					}
				});
		// start
		RootPanel.get().add(homeView);
		eventBus.dispatch(Events.START.name());
	}

}
